package com.zoweunion.mechanic.util.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.zoweunion.mechanic.util.DateUtil;
import com.zoweunion.mechanic.util.constants.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
public class CarDataMocha {

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String intelligentTemplateDetails = "[{\"name\":\"采样时间\",\"company\":\"\",\"tag\":\"sample_time\",\"sort_number\":\"0\"}," +
            "{\"t_id\":61,\"name\":\"运行小时\",\"company\":\"h\",\"tag\":\"OperatingHours\",\"sort_number\":1,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"GPS经度\",\"company\":\"°\",\"tag\":\"GPSlongitude\",\"sort_number\":2,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"GPS纬度\",\"company\":\"°\",\"tag\":\"GPSlatitude\",\"sort_number\":3,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"信号强度\",\"company\":\"dBm\",\"tag\":\"CSQ\",\"sort_number\":4,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"电池电压\",\"company\":\"v\",\"tag\":\"BatVol\",\"sort_number\":5,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"燃油油位\",\"company\":\"%\",\"tag\":\"FuelGauge\",\"sort_number\":6,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"水温\",\"company\":\"℃\",\"tag\":\"IO6\",\"sort_number\":7,\"type\":\"参数变量\"}," +
            "{\"t_id\":61,\"name\":\"油温\",\"company\":\"℃\",\"tag\":\"IO7\",\"sort_number\":8,\"type\":\"参数变量\"}]";


    /**
     * 实时数据
     */
    private static final String realData2 = "{\"data\":{\"sample_time\":\"2019-12-11 10:50:35\",\"OperatingHours\":\"762.8h\",\"GPSlongitude\":\"120.37151°\",\"GPSlatitude\":\"31.50363°\",\"CSQ\":\"28dBm\",\"BatVol\":\"11.7v\",\"FuelGauge\":\"-32%\",\"IO6\":\"52℃\",\"IO7\":\"45℃\"}," +
            "\"mapData\":{\"hasFaultCode\":false,\"adviceState\":\"工作中\",\"adviceTime\":\"00:00\",\"OperatingHours\":\"11.6h\",\"Address\":\"江苏省无锡市新吴区无锡太湖国际科技园运河西路中国传感网国际创新园\",\"CSQ\":\"28dBm\",\"BatVol\":\"11.7v\",\"CurrentOilLevel\":\"0.0\",\"GPSlongitude\":\"120.37050\",\"GPSlatitude\":\"31.50330\"}," +
            "\"variableName\":{\"sample_time\":\"采样时间\",\"OperatingHours\":\"运行小时\",\"GPSlongitude\":\"GPS经度\",\"GPSlatitude\":\"GPS纬度\",\"CSQ\":\"信号强度\",\"BatVol\":\"电池电压\",\"FuelGauge\":\"燃油油位\",\"IO6\":\"水温\",\"IO7\":\"油温\"}}";
    private static final String realData = "{\"data\":{" +
            "\"1939_19\": \"30.0℃\"," +
            "\"1939_18\": \"70.0℃\"," +
            "\"BatVol\": \"11.7v\"," +
            "\"1939_16\": \"27.7V\"," +
            "\"GPSlatitude\": \"31.50363°\"," +
            "\"1939_15\": \"3276.75V\"," +
            "\"1939_14\": \"255.0A\"," +
            "\"1939_13\": \"0.0%\"," +
            "\"1939_12\": \"0.0km/L\"," +
            "\"1939_11\": \"102.5kPa\"," +
            "\"1939_32\": \"0.0\"," +
            "\"1939_9\": \"1775.0℃\"," +
            "\"OperatingHours\": \"9815.35h\"," +
            "\"1939_31\": \"0.0km/h\"," +
            "\"1939_30\": \"89989.0L\"," +
            "\"things_id\": \"17010104005\"," +
            "\"FuelGauge\": \"0.0%\"," +
            "\"1936_4\": \"0.0报警\"," +
            "\"GPSlongitude\": \"120.37151°\"," +
            "\"1939_3\": \"0.0dbm\"," +
            "\"delete_flag\": \"false\"," +
            "\"1939_5\": \"11.0%\"," +
            "\"1939_6\": \"726.625rpm\"," +
            "\"1939_7\": \"108.0kPa\"," +
            "\"1939_8\": \"29.0℃\"," +
            "\"sample_time\": \"2020-02-04 17:12:50\"," +
            "\"1939_29\": \"0.0L\"," +
            "\"1939_28\": \"0.0等待\"," +
            "\"1939_26\": \"102.0%\"," +
            "\"1939_25\": \"510.0kPa\"," +
            "\"1939_24\": \"232.0kPa\"," +
            "\"1939_23\": \"102.0%\"," +
            "\"1939_22\": \"1020.0kPa\"," +
            "\"1939_21\": \"24.0%\"," +
            "\"1939_20\": \"1775.0℃\",}," +
            "\"mapData\":{\"hasFaultCode\":false,\"adviceState\":\"工作中\",\"adviceTime\":\"07:32\",\"OperatingHours\":\"11.6h\",\"Address\":\"江苏省无锡市新吴区无锡太湖国际科技园运河西路中国传感网国际创新园\",\"CSQ\":\"28dBm\",\"BatVol\":\"11.7v\",\"CurrentOilLevel\":\"0.0\",\"GPSlongitude\":\"120.37050\",\"GPSlatitude\":\"31.50330\"}," +
            "\"variableName\":{" +
            "\"sample_time\": \"采样时间\"," +
            "\"GPSlongitude\": \"GPS经度\"," +
            "\"GPSlatitude\": \"GPS纬度\"," +
            "\"1939_3\": \"信号强度\"," +
            "\"1936_4\": \"EBS红灯报警\"," +
            "\"1939_5\": \"发动机扭矩\"," +
            "\"1939_6\": \"发动机转速\"," +
            "\"1939_7\": \"燃油增压器压力\"," +
            "\"1939_8\": \"进气温度\"," +
            "\"1939_9\": \"排气口温度\"," +
            "\"FuelGauge\": \"燃油液位\"," +
            "\"1939_11\": \"大气压\"," +
            "\"1939_12\": \"发动机油耗\"," +
            "\"1939_13\": \"节气门位置\"," +
            "\"1939_14\": \"交流发电机电流\"," +
            "\"1939_15\": \"交流发动机电压\"," +
            "\"1939_16\": \"电器电压\"," +
            "\"BatVol\": \"蓄电池电压\"," +
            "\"1939_18\": \"发动机冷却剂温度\"," +
            "\"1939_19\": \"燃料温度\"," +
            "\"1939_20\": \"发动机油温\"," +
            "\"1939_21\": \"负荷率\"," +
            "\"1939_22\": \"燃油压力\"," +
            "\"1939_23\": \"发动机润滑剂剩余\"," +
            "\"1939_24\": \"机油压力\"," +
            "\"1939_25\": \"冷却剂压力\"," +
            "\"1939_26\": \"冷却剂剩余\"," +
            "\"OperatingHours\": \"发动机总工作小时\"," +
            "\"1939_28\": \"发动机等待启动灯\"," +
            "\"1939_29\": \"短途燃油消耗\"," +
            "\"1939_30\": \"总燃油消耗\"," +
            "\"1939_31\": \"车辆速度\"," +
            "\"1939_32\": \"燃料中水分指示\"" +
            "}}";


    /**
     * 工时
     */
    private static final String carWorkingHStatics = "{" +
            "\"todayHour\":\"11.7\",\"avgHour\":17.9,\"totalHour\":179.3,\"workDays\":10," +
            "\"list\":[{\"date\":\"2019-11-10\",\"value\":0.0},{\"date\":\"2019-11-11\",\"value\":0.0},{\"date\":\"2019-11-12\",\"value\":0.0},{\"date\":\"2019-11-13\",\"value\":\"6.5\"},{\"date\":\"2019-11-14\",\"value\":\"24.0\"},{\"date\":\"2019-11-15\",\"value\":\"24.0\"},{\"date\":\"2019-11-16\",\"value\":\"24.0\"},{\"date\":\"2019-11-17\",\"value\":\"24.0\"},{\"date\":\"2019-11-18\",\"value\":\"24.0\"},{\"date\":\"2019-11-19\",\"value\":\"24.0\"},{\"date\":\"2019-11-20\",\"value\":\"10.2\"},{\"date\":\"2019-11-21\",\"value\":0.0},{\"date\":\"2019-11-22\",\"value\":0.0},{\"date\":\"2019-11-23\",\"value\":0.0},{\"date\":\"2019-11-24\",\"value\":0.0},{\"date\":\"2019-11-25\",\"value\":0.0},{\"date\":\"2019-11-26\",\"value\":0.0},{\"date\":\"2019-11-27\",\"value\":0.0},{\"date\":\"2019-11-28\",\"value\":0.0},{\"date\":\"2019-11-29\",\"value\":0.0},{\"date\":\"2019-11-30\",\"value\":0.0},{\"date\":\"2019-12-01\",\"value\":0.0},{\"date\":\"2019-12-02\",\"value\":0.0},{\"date\":\"2019-12-03\",\"value\":0.0},{\"date\":\"2019-12-04\",\"value\":0.0},{\"date\":\"2019-12-05\",\"value\":0.0},{\"date\":\"2019-12-06\",\"value\":0.0},{\"date\":\"2019-12-07\",\"value\":0.0},{\"date\":\"2019-12-08\",\"value\":0.0},{\"date\":\"2019-12-09\",\"value\":0.0},{\"date\":\"2019-12-10\",\"value\":\"6.9\"},{\"date\":\"2019-12-11\",\"value\":\"11.7\"}]}";

    /**
     * 每日工时
     */
    private static final String carWorkHourDistributionDay = "{\"startTimeList\":[\"08.46\",\"09.47\",\"09.55\",\"11.26\",\"12.36\",\"15.51\",\"16.27\"],\"hours\":[\"0.6\",\"0.0\",\"0.8\",\"1.0\",\"0.8\",\"0.3\",\"2.2\"],\"workHours\":5.7,\"endTimeList\":[\"09.24\",\"09.48\",\"10.45\",\"12.25\",\"13.22\",\"16.10\",\"18.38\"]}";

    /**
     * 车油耗
     */
    private static final String carFuelConsumption = "{\"list\":[{\"date\":\"2019-11-10\",\"value\":0.0},{\"date\":\"2019-11-11\",\"value\":0.0},{\"date\":\"2019-11-12\",\"value\":0.0},{\"date\":\"2019-11-13\",\"value\":\"0.0\"},{\"date\":\"2019-11-14\",\"value\":\"0.0\"},{\"date\":\"2019-11-15\",\"value\":\"0.0\"},{\"date\":\"2019-11-16\",\"value\":\"0.0\"},{\"date\":\"2019-11-17\",\"value\":\"0.0\"},{\"date\":\"2019-11-18\",\"value\":\"0.0\"},{\"date\":\"2019-11-19\",\"value\":\"0.0\"},{\"date\":\"2019-11-20\",\"value\":\"0.0\"},{\"date\":\"2019-11-21\",\"value\":0.0},{\"date\":\"2019-11-22\",\"value\":0.0},{\"date\":\"2019-11-23\",\"value\":0.0},{\"date\":\"2019-11-24\",\"value\":0.0},{\"date\":\"2019-11-25\",\"value\":0.0},{\"date\":\"2019-11-26\",\"value\":0.0},{\"date\":\"2019-11-27\",\"value\":0.0},{\"date\":\"2019-11-28\",\"value\":0.0},{\"date\":\"2019-11-29\",\"value\":0.0},{\"date\":\"2019-11-30\",\"value\":0.0},{\"date\":\"2019-12-01\",\"value\":0.0},{\"date\":\"2019-12-02\",\"value\":0.0},{\"date\":\"2019-12-03\",\"value\":0.0},{\"date\":\"2019-12-04\",\"value\":0.0},{\"date\":\"2019-12-05\",\"value\":0.0},{\"date\":\"2019-12-06\",\"value\":0.0},{\"date\":\"2019-12-07\",\"value\":0.0},{\"date\":\"2019-12-08\",\"value\":0.0},{\"date\":\"2019-12-09\",\"value\":0.0},{\"date\":\"2019-12-10\",\"value\":\"0.0\"},{\"date\":\"2019-12-11\",\"value\":\"0.0\"}],\"currentOilLevel\":\"0.0\"}";

    /**
     * 车油耗工时
     */
    private static final String carFuelConsumptionWorkHours = "{\"totalFuelConsumption\":0.0," +
            "\"list\":[{\"date\":\"2019-11-10\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-11\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-12\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-13\",\"value2\":\"6.5\",\"value\":\"0.0\"},{\"date\":\"2019-11-14\",\"value2\":\"24.0\",\"value\":\"0.0\"},{\"date\":\"2019-11-15\",\"value2\":\"24.0\",\"value\":\"0.0\"},{\"date\":\"2019-11-16\",\"value2\":\"24.0\",\"value\":\"0.0\"},{\"date\":\"2019-11-17\",\"value2\":\"24.0\",\"value\":\"0.0\"},{\"date\":\"2019-11-18\",\"value2\":\"24.0\",\"value\":\"0.0\"},{\"date\":\"2019-11-19\",\"value2\":\"24.0\",\"value\":\"0.0\"},{\"date\":\"2019-11-20\",\"value2\":\"10.2\",\"value\":\"0.0\"},{\"date\":\"2019-11-21\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-22\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-23\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-24\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-25\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-26\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-27\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-28\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-29\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-11-30\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-01\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-02\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-03\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-04\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-05\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-06\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-07\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-08\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-09\",\"value2\":0.0,\"value\":0.0},{\"date\":\"2019-12-10\",\"value2\":\"6.9\",\"value\":\"0.0\"},{\"date\":\"2019-12-11\",\"value2\":\"12.1\",\"value\":\"0.0\"}],\"totalRunningHours\":\"179.7\"}";

    public List<Map<String, Object>> getIntelligentTemplateDetails() {
        return JSON.parseObject(intelligentTemplateDetails, new TypeReference<ArrayList<Map<String, Object>>>() {});
    }

    private List<Map<String, Object>> jsonarrayToLinkedList(Object jsonArray){
        return JSON.parseObject(JSON.toJSONString(jsonArray), new TypeReference<LinkedList<Map<String, Object>>>() {});
    }

    public Map<String, Object> getRealData() {
        Map<String, Object> realDataMap = JSON.parseObject(realData);
        Map<String, Object> map = (Map<String, Object>) realDataMap.get("data");
        map.put("sample_time", DateUtil.formatTime(LocalDateTime.now()));
        JSONObject mapData = (JSONObject) realDataMap.get("mapData");
        // 设置运行时间
        LocalDate endTime = LocalDate.now();
        // 获取工作时长
        Map<String, Object> carWorkingHoursMap = this.getCarWorkingHoursStatistics(endTime, endTime);
        mapData.put("OperatingHours", carWorkingHoursMap.get("todayHour").toString() + "h");

        // 获取燃油油位
        Map<String, Object> carFuelConsumptionMap = this.getCarOilLevelStatistics(endTime, endTime);
        mapData.put("CurrentOilLevel", CarDataStatisticsUtil.round(Double.valueOf(carFuelConsumptionMap.get("fuelTank").toString()), 1) + "L");
        map.put("FuelGauge", carFuelConsumptionMap.get("currentOilLevel").toString() + "%");
        return realDataMap;
    }


    /*public Map<String, Object> getCarWorkingHoursStatistics(LocalDate startTime, LocalDate endTime) {
        String carWorkingHoursStatisticsKey = "mechanic:CarWorkingHoursStatistics:";
        Map<String, Object> resultMap = new HashMap<>(16);
        String carDataMochaSuffix = this.getCarDataMochaSuffix(startTime, endTime);
        // 定义数据列表
        List<Map<String, Object>> dataMapList = new LinkedList<>();
        Object obj = redisTemplate.opsForValue().get(carWorkingHoursStatisticsKey + carDataMochaSuffix);
        if (obj != null) {
            return JSON.parseObject(obj.toString(), new TypeReference<Map<String, Object>>() {});
        }
        // 获取相差天数
        long days = ChronoUnit.DAYS.between(startTime, endTime);
        for (int i = 0; i <= days; i++) {
            LocalDate date1 = startTime.plusDays(i);
            Map<String, Object> data = new HashMap<>(3);
            data.put("date", DateUtil.formatDate(date1));
            data.put("value", CarDataStatisticsUtil.round(new Random().nextDouble() * 4 + 6, 1));
            dataMapList.add(data);
        }

        resultMap.put("list", dataMapList);
        // 设置工时数据
        CarDataStatisticsUtil.setHourData(dataMapList, endTime, resultMap);
        redisTemplate.opsForValue().set(carWorkingHoursStatisticsKey + carDataMochaSuffix, JSON.toJSONString(resultMap),
                formNowToNight12Clock(), TimeUnit.SECONDS);
        return resultMap;
    }*/

    private String workingHoursDistributionStatisticsKey = "mechanic:WorkingHoursDistributionStatistics:${date}";

    public Map<String, Object> workingHoursDistributionStatistics(String date) {
        Object obj = redisTemplate.opsForValue().get(workingHoursDistributionStatisticsKey.replace("${date}", date));
        if (obj != null) {
            return JSON.parseObject(obj.toString(), new TypeReference<Map<String, Object>>() {});
        }

        LinkedList<String> hours = new LinkedList<>(),
                startTimeList = new LinkedList<>(),
                endTimeList = new LinkedList<>(),
                start2TimeList = new LinkedList<>(),
                end2TimeList = new LinkedList<>();
        String startHour1, endHour1,
                startMinute1, endMinute1;
        startHour1 = rangeNumStr(6, 8);
        startMinute1 = rangeNumStr(0, 59);
        endHour1 = rangeNumStr(11, 12);
        endMinute1 = rangeNumStr(0, 59);

        startTimeList.add(CarDataStatisticsUtil.distanceMinuteFromDay(date +" "+ startHour1 + ":" + startMinute1+ ":00"));
        start2TimeList.add(date + " " + startHour1 + ":" + startMinute1 + ":00");
        endTimeList.add(CarDataStatisticsUtil.distanceMinuteFromDay(date +" "+ endHour1 + ":" + endMinute1+ ":00"));
        end2TimeList.add(date + " " + endHour1 + ":" + endMinute1 + ":00");
        hours.add(CarDataStatisticsUtil.distanceMinute(start2TimeList.getLast(), end2TimeList.getLast()));

        startHour1 = rangeNumStr(12, 14);
        endHour1 = rangeNumStr(17, 18);

        startTimeList.add(CarDataStatisticsUtil.distanceMinuteFromDay(date +" "+ startHour1 + ":" + startMinute1+ ":00"));
        start2TimeList.add(date + " " + startHour1 + ":" + startMinute1 + ":00");
        endTimeList.add(CarDataStatisticsUtil.distanceMinuteFromDay(date +" "+ endHour1 + ":" + endMinute1+ ":00"));
        end2TimeList.add(date + " " + endHour1 + ":" + endMinute1 + ":00");
        hours.add(CarDataStatisticsUtil.distanceMinute(start2TimeList.getLast(), end2TimeList.getLast()));

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("startTimeList", startTimeList);
        resultMap.put("hours", hours);
        resultMap.put("endTimeList", endTimeList);

        resultMap.put("startTime2List", start2TimeList);
        resultMap.put("endTime2List", end2TimeList);
        double workHours = CarDataStatisticsUtil.round(hours.stream().map(Double::valueOf).mapToDouble(Double::doubleValue).sum(), 2);
        resultMap.put("workHours", workHours == 0 ? "0.00" : workHours + "");
        redisTemplate.opsForValue().set(workingHoursDistributionStatisticsKey.replace("${date}", date), JSON.toJSONString(resultMap),
                formNowToNight12Clock(), TimeUnit.SECONDS);
        return resultMap;
    }

    public Map<String, Object> getCarWorkingHoursStatistics(LocalDate startTime, LocalDate endTime) {
        int days = DateUtil.getDays(startTime, endTime);

        List<Map<String, Object>> workHoursList = new LinkedList<>();
        LocalDate date;
        Map<String, Object> data;
        for (int i = 0; i <= days; i++) {
            date = startTime.plusDays(i);
            data = new HashMap<>();
            data.put("sample_date", DateUtil.formatDate(date));
            data.put("work_hours_json", JSON.toJSONString(workingHoursDistributionStatistics(DateUtil.formatDate(date))));
            workHoursList.add(data);
        }
        List<Map<String, Object>> runningHoursList = CarDataStatisticsUtil.getConsumption(workHoursList);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("list", runningHoursList);
        // 设置工时数据
        CarDataStatisticsUtil.setHourData(runningHoursList, endTime, resultMap);
        return resultMap;
    }

    private String rangeNumStr(int min, int max){
        return String.format("%02d", rangeNum(min, max));
    }

    private int rangeNum(int min, int max) {
        Random random = new Random();
        int s = random.nextInt(max) % (max - min + 1) + min;
        return s;
    }




    public Map<String, Object> getCarFuelConsumptionStatistics(LocalDate startTime, LocalDate endTime) {
        String carFuelConsumptionStatisticsKey = "mechanic:CarFuelConsumptionStatistics:";
        String carDataMochaSuffix = this.getCarDataMochaSuffix(startTime, endTime);
        double tankCapacity = 300D;
        Map<String, Object> resultMap = new HashMap<>(16);
        // 定义数据列表
        List<Map<String, Object>> dataMapList = new LinkedList<>();
        Object obj = redisTemplate.opsForValue().get(carFuelConsumptionStatisticsKey + carDataMochaSuffix);
        if (obj != null) {
            return JSON.parseObject(obj.toString(), new TypeReference<Map<String, Object>>() {});
        }
        // 获取相差天数
        long days = ChronoUnit.DAYS.between(startTime, endTime);
        Map<String, Object> carWorkingHoursMap = this.getCarWorkingHoursStatistics(startTime, endTime);
        List<Map<String, Object>> hourMapList = this.jsonarrayToLinkedList(carWorkingHoursMap.get("list"));

        for (int i = 0; i <= days; i++) {
            LocalDate date1 = startTime.plusDays(i);
            Map<String, Object> data = new HashMap<>(3);
            data.put("date", DateUtil.formatDate(date1));
            // 计算油位
            data.put("value", CarDataStatisticsUtil.round(tankCapacity * (Double.valueOf(hourMapList.get(i).get("value").toString()) / 24 * 2), 1));
            dataMapList.add(data);
        }

        resultMap.put("list", dataMapList);
        // 当前油位
        if (LocalDate.now().equals(endTime)) {
            resultMap.put("currentOilLevel", dataMapList.get(dataMapList.size() - 1).get("value"));
        }
        redisTemplate.opsForValue().set(carFuelConsumptionStatisticsKey + carDataMochaSuffix, JSON.toJSONString(resultMap),
                formNowToNight12Clock(), TimeUnit.SECONDS);
        return resultMap;
    }

    private final String carOilLevelStatistics = "mechanic:CarOilLevelStatistics:";
    private Map<String, Object> getCarOilLevelStatisticsEveryDay(LocalDate date, String prevFuelGague){

        String carOilLevelStatisticsKey = carOilLevelStatistics + DateUtil.formatDate(date);
        Object obj = redisTemplate.opsForValue().get(carOilLevelStatisticsKey);
        if (obj != null) {
            return JSON.parseObject(obj.toString(), new TypeReference<Map<String, Object>>() {});
        }

        // 数据处理
        LocalDateTime dataStartTime = DateUtil.toLocalDateTime(date, true);
        long distanceMinute = DateUtil.getDistanceMinute(dataStartTime, DateUtil.toLocalDateTime(date, false));

        long interval = 2;
        long loop = distanceMinute / interval;

        double fuelGauge = rangeNum(95, 100);
        if (prevFuelGague != null) {
            fuelGauge = Double.valueOf(prevFuelGague);
            if (fuelGauge < 35) {
                fuelGauge = rangeNum(95, 100);
            }
        }

        LocalDateTime dataTime;
        Map<String, Object> dataMap;

        LinkedList<Map<String, Object>> dataMapList = new LinkedList<>();

        String dateStr = DateUtil.formatDate(date);
        Map<String, Object> workingHoursMap = workingHoursDistributionStatistics(dateStr);
        List<String> startTime2List = (List<String>)workingHoursMap.get("startTime2List");
        List<String> endTime2List = (List<String>)workingHoursMap.get("endTime2List");
        for (int i = 0; i < loop; i++) {
            dataTime = dataStartTime.plusMinutes(i * interval);

            if (!dateStr.equals(DateUtil.formatTime(dataTime).substring(0, 10))) {
                dateStr = DateUtil.formatTime(dataTime).substring(0, 10);

                startTime2List = (List<String>)workingHoursMap.get("startTime2List");
                endTime2List = (List<String>)workingHoursMap.get("endTime2List");
            }

            if (isInTimeList(startTime2List, endTime2List, dataTime)) {
                fuelGauge = fuelGauge - 0.00021 * rangeNum(88, 888) + 0.00008 * rangeNum(55, 555);
            }

            dataMap = new HashMap<>(6);
            dataMap.put("date", dataTime.format(DateTimeFormatter.ofPattern("MM-dd HH:mm")));
            dataMap.put("value", CarDataStatisticsUtil.round(CarDataStatisticsUtil.correctFuelGauge(fuelGauge), 1));
            dataMapList.add(dataMap);
        }
        Map<String, Object> resultMap = new HashMap<>(16);
        resultMap.put("currentOilLevel", CarDataStatisticsUtil.round(Double.valueOf(dataMapList.getLast().get("value").toString()), 1));
        resultMap.put("updateTime", DateUtil.formatTime(LocalDateTime.now()));
        resultMap.put("fuelTank", CarDataStatisticsUtil.round(Double.valueOf(dataMapList.getLast().get("value").toString()) / 100D * 300, 1));
        resultMap.put("fuelGauge", fuelGauge);
        resultMap.put("data", dataMapList);
        redisTemplate.opsForValue().set(carOilLevelStatisticsKey, JSON.toJSONString(resultMap),
                formNowToNight12Clock(), TimeUnit.SECONDS);
        // 保存至redis
        return resultMap;
    }

    private boolean isInTimeList(List<String> startTime2List, List<String> endTime2List, LocalDateTime time) {
        for (int i = 0; i < startTime2List.size(); i++) {
            LocalDateTime startTime = DateUtil.parseTime(startTime2List.get(i));
            LocalDateTime endTime = DateUtil.parseTime(endTime2List.get(i));
            if (!time.isBefore(startTime) && !time.isAfter(endTime)) {
                return true;
            }
        }
        return false;
    }

    /*public Map<String, Object> getCarOilLevelStatistics(LocalDate startTime, LocalDate endTime){

        boolean isToday = startTime.equals(endTime);

        Map<String, Object> carOilLevelEveryDays;
        List<Map<String, Object>> dataMapList = new LinkedList<>();

        if (isToday) {
            carOilLevelEveryDays = getCarOilLevelStatisticsEveryDay(startTime, null);
            dataMapList = (List<Map<String, Object>>) carOilLevelEveryDays.get("data");
            dataMapList.forEach(map -> map.put("date", map.get("date").toString().substring(6)));
            carOilLevelEveryDays.put("data", dataMapList);
            return carOilLevelEveryDays;
        }

        int distanceDays = DateUtil.getDays(startTime, endTime);
        LocalDate dataTime;
        String fuelGauge = null;
        for (int i = 0; i < distanceDays; i++) {
            dataTime = startTime.plusDays(i);
            carOilLevelEveryDays = getCarOilLevelStatisticsEveryDay(dataTime, fuelGauge);
            fuelGauge = carOilLevelEveryDays.get("fuelGauge").toString();
            dataMapList.addAll((List<Map<String, Object>>) carOilLevelEveryDays.get("data"));
        }
        Map<String, Object> resultMap = new HashMap<>(16);
        resultMap.put("currentOilLevel", CarDataStatisticsUtil.round(Double.valueOf(dataMapList.get(dataMapList.size() - 1).get("value").toString()), 1));
        resultMap.put("updateTime", DateUtil.formatTime(LocalDateTime.now()));
        resultMap.put("fuelTank", CarDataStatisticsUtil.round(Double.valueOf(dataMapList.get(dataMapList.size() - 1).get("value").toString()) / 100D * 300, 1));
        resultMap.put("data", dataMapList);
        return resultMap;
    }*/

    public Map<String, Object> getCarOilLevelStatistics(LocalDate startTime, LocalDate endTime){

//        File oilLevelStaticsFile = this.getFile("common/oillevelStatics.json");
        String content = "{}";
        content = this.getFile("/common/oillevelStatics.json");
        Map<String, Object> oilLevelStatics = JSON.parseObject(content, new TypeReference<Map<String, Object>>(){});

        boolean isToday = startTime.equals(endTime);

        if (isToday) {
            List<Map<String, Object>> dataMapList = new LinkedList<>();
            List<Map<String, Object>> dataList = (List<Map<String, Object>>)oilLevelStatics.get("data");
            Map<String, Object> data;

            LocalDateTime dataStartTime = DateUtil.toLocalDateTime(startTime, true);
            String time = DateUtil.formatTime(dataStartTime).substring(0, 10);
            LocalDateTime dataTime;
            long distanceMinutes = DateUtil.getDistanceMinute(dataStartTime, DateUtil.toLocalDateTime(startTime, false));
            for (int i = 0; i < distanceMinutes; i += 2) {
                dataTime = dataStartTime.plusMinutes(i);
                if (!time.equals(DateUtil.formatTime(dataTime).substring(0, 10))) {
                    break;
                }
                dataList.get(i / 2).put("date", DateUtil.formatTime(dataTime).substring(5, 16));
                dataMapList.add(dataList.get(i / 2));
            }
            Map<String, Object> resultMap = new HashMap<>(16);
            resultMap.put("currentOilLevel", CarDataStatisticsUtil.round(Double.valueOf(dataMapList.get(dataMapList.size() - 1).get("value").toString()), 1));
            resultMap.put("updateTime", DateUtil.formatTime(LocalDateTime.now()));
            resultMap.put("fuelTank", CarDataStatisticsUtil.round(Double.valueOf(dataMapList.get(dataMapList.size() - 1).get("value").toString()) / 100D * 300, 1));
            resultMap.put("data", dataMapList);
            return resultMap;
        }

        return oilLevelStatics;
    }

    public Map<String, Object> getDashboard() {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.putIfAbsent(Constants.THINGS_WaterTemperature, 0);
        resultMap.putIfAbsent(Constants.THINGS_RotateSpeed, 0);
        resultMap.putIfAbsent(Constants.THINGS_OilPressure, 0);
        resultMap.putIfAbsent(Constants.THINGS_FuelGauge, 0);
        return resultMap;
    }

    private String getFile(String fileName) {
        InputStream is = this.getClass().getResourceAsStream(fileName);
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s;
        StringBuilder configContentStr = new StringBuilder();
        try {
            while ((s = br.readLine()) != null) {
                configContentStr.append(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return configContentStr.toString();
    }

    public Map<String, Object> getCarFuelConsumptionWorkHoursStatistics(LocalDate startTime, LocalDate endTime) {
        String carFuelConsumptionWorkHoursStatistics = "mechanic:CarFuelConsumptionWorkHoursStatistics:";
        String carDataMochaSuffix = this.getCarDataMochaSuffix(startTime, endTime);
        Map<String, Object> resultMap = new HashMap<>(5);
        double tankCapacity = 300D;
        Object obj = redisTemplate.opsForValue().get(carFuelConsumptionWorkHoursStatistics + carDataMochaSuffix);
        if (obj != null) {
            return JSON.parseObject(obj.toString(), new TypeReference<Map<String, Object>>() {});
        }
        Map<String, Object> carWorkingHoursMap = this.getCarWorkingHoursStatistics(startTime, endTime);
        List<Map<String, Object>> hourMapList = this.jsonarrayToLinkedList(carWorkingHoursMap.get("list"));

        Map<String, Object> carFuelConsumptionMap = this.getCarFuelConsumptionStatistics(startTime, endTime);
        List<Map<String, Object>> fuelConsumptionMapList = this.jsonarrayToLinkedList(carFuelConsumptionMap.get("list"));

        for (int i = 0; i < fuelConsumptionMapList.size(); i++) {
            fuelConsumptionMapList.get(i).put("value", tankCapacity - Double.valueOf(fuelConsumptionMapList.get(i).get("value").toString()));
            fuelConsumptionMapList.get(i).put("value2", hourMapList.get(i).get("value"));
        }

        resultMap.put("list", fuelConsumptionMapList);
        resultMap.put("totalFuelConsumption", CarDataStatisticsUtil.round(fuelConsumptionMapList.stream().mapToDouble(o1 -> Double.valueOf(o1.get("value").toString())).sum(), 1));
        resultMap.put("totalRunningHours", CarDataStatisticsUtil.round(hourMapList.stream().mapToDouble(o1 -> Double.valueOf(o1.get("value").toString())).sum(), 1));
        redisTemplate.opsForValue().set(carFuelConsumptionWorkHoursStatistics + carDataMochaSuffix, JSON.toJSONString(resultMap),
                formNowToNight12Clock(), TimeUnit.SECONDS);
        return resultMap;
    }

    public Map<String, Object> getCarFuelConsumptionWorkHoursStatistics2(String date) {
        String yearDate = null,
                monthDate = null,
                currentMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));

        boolean isCurrentMonth = false;
        LocalDate startTime, endTime;
        if (date.length() == 4) {
            yearDate = date;
            startTime = LocalDate.of(Integer.valueOf(date), 1, 1);
            endTime = LocalDate.of(Integer.valueOf(date), 12, 31);
        } else {
            monthDate = date;
            startTime = DateUtil.parseDate(monthDate + "-01");
            if (monthDate.equals(currentMonth)) {
                endTime = LocalDate.now();
            } else {
                endTime = DateUtil.parseDate(monthDate + "-01").with(TemporalAdjusters.lastDayOfMonth());
            }
        }

        String carFuelConsumptionWorkHoursStatistics = "mechanic:CarFuelConsumptionWorkHoursStatistics2:";
        String carDataMochaSuffix = this.getCarDataMochaSuffix(startTime, endTime);
        Map<String, Object> resultMap = new HashMap<>(5);

        double tankCapacity = 300D;
        Object obj = redisTemplate.opsForValue().get(carFuelConsumptionWorkHoursStatistics + carDataMochaSuffix);
        if (obj != null) {
            return JSON.parseObject(obj.toString(), new TypeReference<Map<String, Object>>() {});
        }
        Map<String, Object> carWorkingHoursMap = this.getCarWorkingHoursStatistics(startTime, endTime);
        List<Map<String, Object>> hourMapList = this.jsonarrayToLinkedList(carWorkingHoursMap.get("list"));

        Map<String, Object> carFuelConsumptionMap = this.getCarFuelConsumptionStatistics(startTime, endTime);
        List<Map<String, Object>> fuelConsumptionMapList = this.jsonarrayToLinkedList(carFuelConsumptionMap.get("list"));

        int workDays = 0,
                continuousWorkDays = 0,
                size = fuelConsumptionMapList.size();
        for (int i = 0; i < fuelConsumptionMapList.size(); i++) {
            fuelConsumptionMapList.get(i).put("value", tankCapacity - Double.valueOf(fuelConsumptionMapList.get(i).get("value").toString()));
            fuelConsumptionMapList.get(i).put("value2", hourMapList.get(i).get("value"));
            workDays++;
            continuousWorkDays++;
        }

        double avgHours = 0D,
                totalWorkHours = 0D,
                totalConsumption = 0D;
        OptionalDouble optionalAvgHours = fuelConsumptionMapList.stream().mapToDouble(map -> Double.valueOf(map.get("value2").toString())).average();
        totalConsumption = fuelConsumptionMapList.stream().mapToDouble(map -> Double.valueOf(map.get("value2").toString())).sum();

        if (optionalAvgHours.isPresent()) {
            avgHours = optionalAvgHours.getAsDouble();
        }

        if (monthDate != null) {
            for (Map<String, Object> fuelConsumptionMap : fuelConsumptionMapList) {
                fuelConsumptionMap.put("date", fuelConsumptionMap.get("date").toString().substring(8, 10));
            }
        } else if (yearDate != null) {
            List<Map<String, Object>> dataList = new ArrayList<>();
            Map<String, Object> item = new HashMap<>();
            for (int i = 1; i <= 12; i++) {
                String month = String.format("%02d", i);
                double monthWorkHours = 0D,
                        monthFuelConsumption = 0D;

                for (Map<String, Object> fuelConsumptionMap : fuelConsumptionMapList) {

                    String idate = fuelConsumptionMap.get("date").toString().substring(5, 7);
                    if (idate.equals( month)) {
                        item = new HashMap<>();
                        item.put("date", idate);
                        monthFuelConsumption += Double.valueOf(fuelConsumptionMap.get("value").toString());
                        item.put("value", monthFuelConsumption);
                        monthWorkHours += Double.valueOf(fuelConsumptionMap.get("value2").toString());
                        item.put("value2", monthWorkHours);
                        dataList.add(item);
                    }
                }
            }
            fuelConsumptionMapList = dataList;
        }

        resultMap.put("workDays", workDays);
        resultMap.put("continuousWorkDays", continuousWorkDays);
        resultMap.put("avgHours", avgHours);
        resultMap.put("totalWorkHours", CarDataStatisticsUtil.round(totalWorkHours, 2));
        resultMap.put("totalConsumption", CarDataStatisticsUtil.round(totalConsumption, 2));
        resultMap.put("list", fuelConsumptionMapList);

        redisTemplate.opsForValue().set(carFuelConsumptionWorkHoursStatistics + carDataMochaSuffix, JSON.toJSONString(resultMap),
                formNowToNight12Clock(), TimeUnit.SECONDS);
        return resultMap;
    }

    private String getCarDataMochaSuffix(LocalDate startTime, LocalDate endTime){
        return DateUtil.formatDate(startTime) + "-" + DateUtil.formatDate(endTime);
    }


    private long formNowToNight12Clock() {
        return Duration.between(LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0),
                LocalDateTime.now()).getSeconds();
    }
}
